/**
 * 版权所有 2009-2012山东新北洋信息技术股份有限公司
 * 保留所有权利。
 */
package com.linyaonan.leetcode.medium._16_26;

import java.util.LinkedList;
import java.util.Stack;

/**
 * @ProjectName: leetcode
 * @Package: com.linyaonan.leetcode.medium._16_26
 * @ClassName: Calculate
 * @Author: linyaonan
 * @Date: 2020/4/8 17:54
 */
public class Calculate {

    public int calculate(String s) {
        // 操作符栈
        LinkedList<Character> fStack = new LinkedList<>();
        // 数值栈
        LinkedList<Integer> nStack = new LinkedList<>();
        StringBuilder sb = new StringBuilder();
        // 去除所有空格
        s = s.replace(" ", "");
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == ' ') {
                continue;
            }
            if (Character.isDigit(c)) {
                sb.append(c);
                // 数字下一位为非数字或者为字符结束
                if ((i == s.length() - 1)
                        || ((i + 1) < s.length() && !Character.isDigit(s.charAt(i + 1)))) {
                    nStack.add(Integer.valueOf(sb.toString()));
                    // 清空
                    sb.delete(0, sb.length());
                }

            } else {
                if (fStack.isEmpty()) {
                    fStack.add(c);
                } else {
                    Character peek = fStack.peekLast();
                    // 原有操作符优先级低
                    if (peek == '-' || peek == '+') {
                        fStack.add(c);
                    } else {
                        // 操作符优先级高
                        Integer first = nStack.removeLast();
                        Integer second = nStack.removeLast();
                        if (peek == '*') {
                            nStack.add(second * first);
                        } else {
                            nStack.add(second / first);
                        }
                        fStack.removeLast();
                        fStack.add(c);
                    }
                }
            }
        }
        if (!fStack.isEmpty()) {
            // 最后的乘除号处理
            if (fStack.peekLast() == '*' || fStack.peekLast() == '/') {
                Integer first = nStack.removeLast();
                Integer second = nStack.removeLast();
                Character c = fStack.removeLast();
                if (c == '*') {
                    nStack.add(second * first);
                } else {
                    nStack.add(second / first);
                }
            }
        }

        // 从头处理
        while (!fStack.isEmpty()) {
            Integer first = nStack.remove();
            Integer second = nStack.remove();
            Character c = fStack.remove();
            if (c == '+') {
                nStack.addFirst(first + second);
            } else {
                nStack.addFirst(first - second);
            }
        }
        return nStack.removeLast();
    }

    public static int calculate2(String s) {
        s = s.replace(" ", "");
        Stack<Integer> stack = new Stack<>();
        char oper = '+';
        int num = 0;
        int n = s.length();
        for (int i = 0; i < n; i++) {
            char c = s.charAt(i);
            if (!isOper(c)) {
                num = num * 10 + (c - '0');
            }
            if (isOper(c) || i == n - 1) {
                int pre;
                switch (oper) {
                    case '+':
                        stack.push(num);
                        break;
                    case '-':
                        stack.push(-num);
                        break;
                    case '*':
                        pre = stack.pop();
                        stack.push(pre * num);
                        break;
                    case '/':
                        pre = stack.pop();
                        stack.push(pre / num);
                        break;
                    default:
                }
                oper = c;
                num = 0;
            }

        }
        int res = 0;
        while (!stack.isEmpty()) {
            res += stack.pop();
        }
        return res;
    }
    private static boolean isOper(char s) {
        return s == '+' || s == '-' || s == '*' || s == '/';
    }

}
